<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>1.4.1-运行时和编译时</title>
</head>
<body>
    
</body>
    <script>
        /**
         * 纯运行时的、运行时 + 编译时的或纯编译时的
         * - 纯运行时
         * -- 它没有编译的过程，因此我们没办法分析用户提供的内容
         * - 加入编译步骤
         * -- 可以分析用户提供的内容
         * -- 可以在编译的时候提取信息
         * -- 可以做进一步的优化
         * - 纯编译时
         * -- 它也可以分析用户提供的内容
         * -- 性能可能会更好，但是这种做法有损灵活性，
         *      即用户提供的内容必须编译后才能用
         * 
         * Svelte 就是纯编译时的框架
         * - 但是它的真实性能可能达不到理论高度
         * Vue.js 3 仍然保持了运行时 + 编译时的架构
         * - 其性能甚至不输纯编译时的框架
         * 
        */
        function Render(obj, root) {
            const el = document.createElement(obj.tag)
            if (typeof obj.children === 'string') {
                const text = document.createTextNode(obj.children)
                el.appendChild(text)
            } else if (obj.children) {
                // 数组，递归调用 Render，使用 el 作为 root 参数
                obj.children.forEach((child) => Render(child, el))
            }

            // 将元素添加到 root
            root.appendChild(el)
        }

        /**
         * 纯运行时
         * - 为 Render 函数提供了一个树型结构的数据对象
         * - 不涉及任何额外的步骤
         * */ 
        const obj = {
            tag: 'div',
            children: [
                { tag: 'span', children: 'hello world' }
            ]
        }
        // 渲染到 body 下
        Render(obj, document.body)
       

        /**
         * 编译时 + 运行时
         * - 既支持运行时，用户可以直接提供数据对象从而无须编译
         * - 又支持编译时，用户可以提供 HTML 字符串，我们将其编译为数据对象后再交给运行时处理
         * - 准确地说，上面的代码其实是运行时编译, 意思是代码运行的时候才开始编译
         * - 可以在构建的时候就执行 Compiler 程序将用户提供的内容编译好，等到运行时就无须编译
         * */ 
         const html = `
            <div>
                <span>hello world</span>
            </div>
        `
        // 调用 Compiler 编译得到树型结构的数据对象
        const obj1 = Compiler(html)
        // 再调用 Render 进行渲染
        Render(obj1, document.body)

        /**
         * 纯编译时
         * - 只需要一个 Compiler 函数就可以了，连 Render 都不需要了
         * - 不支持任何运行时内容，用户的代码通过编译器编译后才能运行
        */
        Compiler(html)
    </script>
</html>